#ifndef __HV_TCP_SERVER_XDG__HPP
#define __HV_TCP_SERVER_XDG__HPP

#include <string>
#include <functional>

#include "hv/TcpServer.h"
#include "hv/hsysinfo.h"
#include "hv/hasync.h" // 引入 hv::async 以启动和管理后台线程池



namespace xdg
{

    class TcpServer {
    public:
        /**
         * @brief 预设的解包模式枚举
         */
        enum class UnpackMode {
            NO_UNPACK,              ///< 不进行任何解包，onMessage 会收到原始数据流
            FIXED_LENGTH,           ///< 按固定的128字节长度拆包
            DELIMITER,              ///< 按 "\r\n" 分隔符拆包
            LENGTH_FIELD_32BIT      ///< 按 "4字节网络序长度 + 包体" 格式拆包
        };

        /******************************************构造 / 析构函数******************************************/
    public:
        /**
         * @brief 构造函数
         * @param host 服务器监听地址 (默认0.0.0.0)
         * @param port 服务器监听端口 (默认9999)
         */
        explicit TcpServer(const std::string& host = "0.0.0.0", int port = 9999) {
            m_tcpServer = std::make_unique<hv::TcpServer>();

            // 直接在构造时设置端口和地址
            m_tcpServer->port = port;
            m_tcpServer->host = host;
        }

        /**
         * @brief 析构函数
         * @note 析构函数不再负责清理全局的 hv::async 线程池，
         * 这应该由应用程序的 main 函数在退出前调用 hv::async::cleanup() 来完成。
         */
        ~TcpServer() {
            hv::async::cleanup();
        }

        /******************************************核心功能方法******************************************/
    public:
        /**
         * @brief 设置工作线程数，设置的是工作线程的数量，不是同时能处理的客户端请求数量。
         * @param num 工作线程数量，0为CPU的核心数 * 2
         */
        inline void setThreadNum(size_t num) {
            if (num < 1) { num = get_ncpu() * 2; }
            m_workerThreadNum = num;
        }
        /**
         * @brief 设置hv::async 的后台线程池最小线程数
         * @param num 线程数量，0为CPU的核心数 * 2
         */
        inline void setMinAsyncThreads(size_t num) {
            if (num < 1) { num = get_ncpu() * 2; }
            m_minAsyncThreads = num;
        }
        /**
         * @brief 设置hv::async 的后台线程池最大线程数
         * @param num 工作线程数量，0为CPU的核心数 * 8
         */
        inline void setMaxAsyncThreads(size_t num) {
            if (num < 1) { num = get_ncpu() * 2; }
            m_maxAsyncThreads = num;
        }

        /**
         * @brief 设置最大连接数
         * @param num 最大连接数量，0为 10000 (1w)
         */
        inline void setMaxConnectionNum(size_t num) {
            if (num < 1) { num = 10000; }
            m_maxConnectionNum = num;
        }

        /**
         * @brief 设置最大包长度限制
         * @param num 最大包长度限制，0为 2MB
         */
        inline void setPackageMaxLength(size_t num) {
            if (num < 1) { num = DEFAULT_PACKAGE_MAX_LENGTH; }
            m_packMaxLen = num;
        }

        /**
         * @brief 设置新连接的负载均衡策略
         * @param lb 负载均衡策略枚举
         * @details
         * - LB_RoundRobin (默认): 轮询策略，按顺序将新连接分配给下一个线程。
         * - LB_LeastConnections: 最少连接数策略，将新连接分配给当前连接数最少的线程。
         * - LB_Random: 随机策略。
         * - LB_IpHash: 源IP哈希策略，确保来自同一IP的连接总是分配给同一个线程。
         */
        inline void setLoadBalance(load_balance_e lb) {
            m_tcpServer->setLoadBalance(lb);
        }

        /**
         * @brief 设置预定义的自定义数据包解包规则
         * @param mode 解包模式枚举
         * @note 这是解决TCP粘包/半包问题的关键，onMessage 回调函数，收到的数据是完整的包：包头+内容。
         */
        void setUnpack(UnpackMode mode) {
            // 不进行任何解包
            if (mode == UnpackMode::NO_UNPACK) {
                // 则向底层的 hv::TcpServer 传递 nullptr，以禁用解包功能。
                // 在这种模式下，onMessage 回调将收到原始的、未经处理的数据块。
                m_tcpServer->setUnpack(nullptr);
                return;
            }

            // --- 以下为启用解包规则的配置 ---

            switch (mode) {
                // 情况一：按固定长度解包
            case UnpackMode::FIXED_LENGTH:
                m_unpackSetting.mode = UNPACK_BY_FIXED_LENGTH; // 设置模式为“按固定长度解包”
                m_unpackSetting.fixed_length = 128;  // 设置每个包的固定长度为 128 字节
                break;

                // 情况二：按分隔符解包
            case UnpackMode::DELIMITER:

                m_unpackSetting.mode = UNPACK_BY_DELIMITER; // 设置模式为“按分隔符解包”
                m_unpackSetting.delimiter[0] = '\r'; // 设置分隔符为 "\r\n"
                m_unpackSetting.delimiter[1] = '\n';
                m_unpackSetting.delimiter_bytes = 2; // 设置分隔符的长度为 2 字节
                break;

                // 情况三：按长度字段解包（最常用）
            case UnpackMode::LENGTH_FIELD_32BIT:
                m_unpackSetting.mode = UNPACK_BY_LENGTH_FIELD; // 设置模式为“按长度字段解包”
                m_unpackSetting.body_offset = 4; // 设置包体相对于整个数据包起始位置的偏移量。包头占4个字节，所以包体从第4个字节开始。
                m_unpackSetting.length_field_offset = 0; // 设置长度字段本身相对于数据包起始位置的偏移量。因为长度字段就在包的最前面，所以偏移为0。
                m_unpackSetting.length_field_bytes = 4; // 设置长度字段本身占用的字节数。这里是4字节（32位）。
                m_unpackSetting.length_field_coding = ENCODE_BY_LITTEL_ENDIAN; // 设置长度字段的字节序。这里设置为小端序。
                m_unpackSetting.length_adjustment = 0;// 长度调整值，用于从包头长度计算出包体长度。公式: body_len = header_len + length_adjustment
                break;

                // 默认情况或未知的枚举值
            default:
                m_tcpServer->setUnpack(nullptr); // 同样禁用解包功能，确保行为安全可预测。
                return;
            }

            m_tcpServer->setUnpack(&m_unpackSetting); // 将内部配置好的 m_unpackSetting 结构体的地址传递给底层的 hv::TcpServer
        }

        /**
         * @brief 设置完全自定义的数据包解包规则 (高级)
         * @param setting 指向自定义解包规则配置的指针
         * @note 保留此重载版本以提供最大的灵活性
         */
        inline void setUnpack(unpack_setting_t* setting) {
            m_tcpServer->setUnpack(setting);
        }

        /**
         * @brief 启用 SSL/TLS 加密
         * @param opt SSL/TLS 配置选项
         */
        inline void withTLS(hssl_ctx_opt_t* opt = nullptr) {
            m_tcpServer->withTLS(opt);
        }

        /**
         * @brief 启动服务器
         * @param wait 是否等待所有后台线程启动完毕后再返回 (默认 true)
         */
        void start(bool wait = true) {
            if (m_packMaxLen < 1) { m_packMaxLen = DEFAULT_PACKAGE_MAX_LENGTH; }
            m_unpackSetting.package_max_length = m_packMaxLen; // 设置最大包长（2MB），如果超过此长度，则断开连接

            if (m_maxConnectionNum < 1) { m_maxConnectionNum = 10000; }
            m_tcpServer->setMaxConnectionNum(m_maxConnectionNum);  // 设置最大连接数

            if (m_workerThreadNum < 1) { m_workerThreadNum = get_ncpu() * 2; }
            m_tcpServer->setThreadNum(m_workerThreadNum); // 设置工作线程数

            // 启动 hv::async 的后台线程池，用于执行异步任务
            if (m_minAsyncThreads < 1) { m_minAsyncThreads = get_ncpu() * 2; }
            if (m_maxAsyncThreads < 1) { m_maxAsyncThreads = get_ncpu() * 8; }
            hv::async::startup(m_minAsyncThreads, m_maxAsyncThreads);


            // 设置内部的 onMessage 包装器
            if (m_userOnMessage) {
                // 如果提供了，就给底层的 hv::TcpServer 设置我们自己的 Lambda 函数作为 onMessage 处理器。
                // 这个 Lambda 函数将作为“调度员”，负责将任务从 I/O 线程转发到后台线程。
                m_tcpServer->onMessage = [this](const hv::TcpServer::TSocketChannelPtr& channel, hv::Buffer* buf) {
                    // 复制数据，以保证其生命周期能安全地跨越线程
                    std::string msg_copy((char*)buf->data(), buf->size());

                    // 使用 hv::async 将真正的业务逻辑处理抛到后台线程池。捕获用户提供的回调函数、连接通道的智能指针和刚刚复制的数据。
                    hv::async(
                        [user_cb = this->m_userOnMessage, channel, msg = std::move(msg_copy)]()
                        {
                            // 为了匹配用户回调的参数类型 (hv::Buffer*)，用复制过来的数据，创建一个临时的、在当前栈上的 hv::Buffer 对象。
                            // 此时的数据是安全的，因为它由 msg (std::string) 持有。
                            hv::Buffer temp_buf((void*)msg.data(), msg.size());
                            // 调用用户真正的 onMessage 回调，并传入安全的临时 Buffer。
                            user_cb(channel, &temp_buf);
                        }
                    );
                    };
            } // if (m_userOnMessage)
            // 所有准备工作就绪后，启动底层的 hv::TcpServer。
            m_tcpServer->start(wait);
        }

        /**
         * @brief 停止服务器
         */
        inline void stop() {
            m_tcpServer->stop();
        }

        /**
         * @brief 返回当前连接数
         * @return 当前客户端连接总数
         */
        inline size_t connectionNum() {
            return m_tcpServer->connectionNum();
        }

        /**
         * @brief 遍历所有连接并执行操作
         * @param fn 要对每个连接执行的函数
         * @return 成功遍历的连接数量
         */
        inline int foreachChannel(std::function<void(const hv::TcpServer::TSocketChannelPtr& channel)> fn) {
            return m_tcpServer->foreachChannel(fn);
        }

        /**
         * @brief 向所有连接的客户端广播消息
         * @param data 要发送的数据指针
         * @param size 数据长度
         * @return 成功发送的客户端数量
         */
        inline int broadcast(const void* data, int size) {
            return m_tcpServer->broadcast(data, size);
        }

        /**
         * @brief 向所有连接的客户端广播消息
         * @param str 要发送的字符串
         * @return 成功发送的客户端数量
         */
        inline int broadcast(const std::string& str) {
            return m_tcpServer->broadcast(str);
        }

        /******************************************回调函数设置******************************************/
    public:
        /**
         * @brief 设置连接/断开事件的回调函数 (在 I/O 线程中执行)
         */
        inline void onConnection(std::function<void(const hv::TcpServer::TSocketChannelPtr&)> onConnect) {
            m_tcpServer->onConnection = onConnect;
        }

        /**
         * @brief 设置收到消息事件的回调函数 (将在后台业务线程池中执行)
         */
        inline void onMessage(std::function<void(const hv::TcpServer::TSocketChannelPtr&, hv::Buffer*)> onMsg) {
            m_userOnMessage = onMsg;
        }

        /**
         * @brief 设置数据发送完成事件的回调函数 (在 I/O 线程中执行)
         */
        inline void onWriteComplete(std::function<void(const hv::TcpServer::TSocketChannelPtr&, hv::Buffer*)> onWriteCom) {
            m_tcpServer->onWriteComplete = onWriteCom;
        }

        /******************************************私有成员变量******************************************/
    private:
        // 底层 hv::TcpServer 的实例指针
        std::unique_ptr<hv::TcpServer>  m_tcpServer;
        // 用于存储由枚举生成的解包配置，确保其生命周期
        unpack_setting_t                m_unpackSetting;
        // 用于存储用户提供的 onMessage 回调，以便在包装器中调用
        std::function<void(const hv::TcpServer::TSocketChannelPtr&, hv::Buffer*)>  m_userOnMessage;

        size_t m_workerThreadNum; // 工作线程数
        size_t m_minAsyncThreads; // 最小异步线程数
        size_t m_maxAsyncThreads; // 最大异步线程数
        size_t m_maxConnectionNum; // 最大连接数
        size_t m_packMaxLen; // 最大包长度

    };

} // namespace xdg

#endif // __HV_TCP_SERVER_XDG__HPP





